package com.xwj.coupon.user.framework.ratelimit;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description 静态窗口限流服务
 * @Author xwj
 * @Date 2025/8/23
 */
@Service
@Slf4j
public class RateLimitService {

    private final Map<String, AtomicReference<WindowInfo>> resourceWindowMap = new ConcurrentHashMap<>();

    public boolean allowRequest(String resource,int windowSize,int maxRequestCount){
        long currentTime = System.currentTimeMillis() / 1000;
        long startTime = currentTime - (currentTime % windowSize);

        AtomicReference<WindowInfo> windowRef = resourceWindowMap.computeIfAbsent(resource, k -> new AtomicReference<>(new WindowInfo(new AtomicInteger(0), maxRequestCount)));

        while(true){
            WindowInfo windowInfo = windowRef.get();
            if(windowInfo.startTime != startTime){
                WindowInfo newWindowInfo = new WindowInfo(new AtomicInteger(1), startTime);
                if(windowRef.compareAndSet(windowInfo,newWindowInfo)){
                    log.info("新请求");
                    return true;
                }
                continue;
            }
            //计数
            int count = windowInfo.requestCount.get();
            if(count<maxRequestCount){
                if(windowInfo.requestCount.compareAndSet(count,count+1)){
                    log.info("当前请求数：{}",count+1);
                    return true;
                }
            }
            else{
                log.warn("当前请求数：{}，限制",count);
                return false;
            }
        }
    }

    private static class WindowInfo{

        public final long startTime;

        public final AtomicInteger requestCount;

        public WindowInfo(AtomicInteger requestCount, long startTime) {
            this.requestCount = requestCount;
            this.startTime = startTime;
        }
    }
}
